package monitor

import (
	"fcs-api/src/monitor/data"
	"fmt"
	"strings"
)

type MetricValue struct {
	Value           float64           `json:"value"`
	DimensionsValue map[string]string `json:"dimensions_value"`
}

func (m *MetricValue) String() string {
	return fmt.Sprintf("<MetricValue : value: %v, dimensions_value: %s>",
		m.Value, m.DimensionsValue)
}

type Metric struct {
	Type       string   `json:"type"`
	Name       string   `json:"name"`
	ResourceId string   `json:"resource_id"`
	Help       string   `json:"help"`
	Dimensions []string `json:"dimensions"`
}

func (m *Metric) String() string {
	return fmt.Sprintf("<Metric : type: %s, name: %s, resource_id: %s, help: %s, dimensions: %s>",
		m.Type, m.Name, m.ResourceId, m.Help, m.Dimensions)
}

func GetFcsMetricValue(metricName string, dimension []string, resourceId string) MetricValue {

	var fcsMetricValue MetricValue
	var usage float64
	var skipSwitch bool

	if len(InvokeMap) == 0 {
		skipSwitch = true
		usage = 0
	} else if !strings.Contains(resourceId, Region) && !strings.Contains(InvokeListStr, resourceId) { //没被调用
		skipSwitch = true
		usage = 0
	}
	//xxx-user
	createName := strings.Replace(resourceId, Region + "-", "", -1)

	if !skipSwitch {
		switch metricName {
		case Fcs_duration:
			invokes := InvokeMap[resourceId]
			d := 0
			for _, invoke := range invokes {
				d = d + invoke.RuntimeDuration
			}
			usage = float64(d) / float64(len(invokes)) / 1000
		case Fcs_avg_memory:
			invokes := InvokeMap[resourceId]
			m := 0
			for _, invoke := range invokes {
				m = m + invoke.MemoryUsage
			}
			usage = float64(m) / float64(len(invokes)) / 1024 / 1024
		case Fcs_max_memory:
			invokes := InvokeMap[resourceId]
			m := 0
			for _, invoke := range invokes {
				if invoke.MemoryUsage > m {
					m = invoke.MemoryUsage
				}
			}
			usage = float64(m) / 1024 / 1024
		case Fcs_function_usage:
			invokes := InvokeMap[resourceId]
			u := float64(0)
			for _, invoke := range invokes {
				u = u + (float64(invoke.MemoryUsage)/1024/1024/1024)*(float64(invoke.RuntimeDuration)/1000) // GB*S
			}
			usage = u
		case Fcs_region_duration:
			d, i := 0, 0
			for _, invoke := range InvokeList {
				if data.CreateIdForNameMap[invoke.Creator] == createName {
					d = d + invoke.RuntimeDuration
					i = i + 1
				}
			}
			if i == 0 {
				usage = 0
			} else {
				usage = float64(d) / float64(i) / 1000
			}
		case Fcs_region_avg_memory:
			m, i := 0, 0
			for _, invoke := range InvokeList {
				if data.CreateIdForNameMap[invoke.Creator] == createName {
					m = m + invoke.MemoryUsage
					i = i + 1
				}
			}
			if i == 0 {
				usage = 0
			} else {
				usage = float64(m) / float64(i) / 1024 / 1024
			}
		case Fcs_region_max_memory:
			m := 0
			for _, invoke := range InvokeList {
				if data.CreateIdForNameMap[invoke.Creator] == createName {
					if invoke.MemoryUsage > m {
						m = invoke.MemoryUsage
					}
				}
			}
			usage = float64(m) / 1024 / 1024
		case Fcs_region_function_usage:
			u := float64(0)
			for _, invoke := range InvokeList {
				if data.CreateIdForNameMap[invoke.Creator] == createName {
					u = u + (float64(invoke.MemoryUsage)/1024/1024/1024)*(float64(invoke.RuntimeDuration)/1000)
				}
			}
			usage = u
		case Fcs_total_invocations:
			invokes := InvokeMap[resourceId]
			usage = float64(len(invokes))
		case Fcs_billable_invocations:
			invokes := InvokeMap[resourceId]
			i := 0
			for _, invoke := range invokes {
				if invoke.ReturnCode >= 200 && invoke.ReturnCode <= 210 {
					i = i + 1
				}
			}
			usage = float64(i)
		case Fcs_error_invocations:
			invokes := InvokeMap[resourceId]
			i := 0
			for _, invoke := range invokes {
				if invoke.ReturnCode >= 400 && invoke.ReturnCode <= 600 {
					i = i + 1
				}
			}
			usage = float64(i)
		case Fcs_billable_invocations_percent:
			invokes := InvokeMap[resourceId]
			i := 0
			for _, invoke := range invokes {
				if invoke.ReturnCode >= 200 && invoke.ReturnCode <= 210 {
					i = i + 1
				}
			}
			usage = float64(i) / float64(len(invokes)) * 100
		case Fcs_error_invocations_percent:
			invokes := InvokeMap[resourceId]
			i := 0
			for _, invoke := range invokes {
				if invoke.ReturnCode >= 400 && invoke.ReturnCode <= 600 {
					i = i + 1
				}
			}
			usage = float64(i) / float64(len(invokes)) * 100
		case Fcs_region_total_invocations:
			i := 0
			for _, invoke := range InvokeList {
				if data.CreateIdForNameMap[invoke.Creator] == createName {
					i = i + 1
				}
			}
			usage = float64(i)
		case Fcs_region_billable_invocations:
			i := 0
			for _, invoke := range InvokeList {
				if data.CreateIdForNameMap[invoke.Creator] == createName {
					if invoke.ReturnCode >= 200 && invoke.ReturnCode <= 210 {
						i = i + 1
					}
				}
			}
			usage = float64(i)
		case Fcs_region_error_invocations:
			i := 0
			for _, invoke := range InvokeList {
				if data.CreateIdForNameMap[invoke.Creator] == createName {
					if invoke.ReturnCode >= 400 && invoke.ReturnCode <= 600 {
						i = i + 1
					}
				}
			}
			usage = float64(i)
		case Fcs_region_billable_invocations_percent:
			i, ti := 0, 0
			for _, invoke := range InvokeList {
				if data.CreateIdForNameMap[invoke.Creator] == createName {
					ti = ti + 1
					if invoke.ReturnCode >= 200 && invoke.ReturnCode <= 210 {
						i = i + 1
					}
				}
			}
			if ti == 0 {
				usage = 0
			} else {
				usage = float64(i) / float64(ti) * 100
			}
		case Fcs_region_error_invocations_percent:
			i, ti := 0, 0
			for _, invoke := range InvokeList {
				if data.CreateIdForNameMap[invoke.Creator] == createName {
					ti = ti + 1
					if invoke.ReturnCode >= 400 && invoke.ReturnCode <= 600 {
						i = i + 1
					}
				}
			}
			if ti == 0 {
				usage = 0
			} else {
				usage = float64(i) / float64(ti) * 100
			}
		}
	}
	if !strings.Contains(resourceId, Region) {
		r := data.ResourceMap[resourceId]
		dimensionsValue := make(map[string]string)
		dimensionsValue[dimension[0]] = r.CreatorName
		dimensionsValue[dimension[1]] = r.FunctionName
		dimensionsValue[dimension[2]] = r.RegionCode
		dimensionsValue[dimension[3]] = r.GroupId
		fcsMetricValue.DimensionsValue = dimensionsValue
		fcsMetricValue.Value = usage
	} else {
		dimensionsValue := make(map[string]string)
		dimensionsValue[dimension[0]] = createName
		dimensionsValue[dimension[1]] = resourceId
		dimensionsValue[dimension[2]] = Region
		fcsMetricValue.DimensionsValue = dimensionsValue
		fcsMetricValue.Value = usage
	}
	return fcsMetricValue
}
